package com.xdap.common.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xdap.common.constant.ExceptionMessage;
import com.xdap.common.consts.ComConst;
import com.xdap.common.utils.JwtUtils;
import com.xdap.motor.exception.XDapSystemException;
import com.xdap.runtime.service.RuntimeAppContextService;
import com.xdap.common.exception.XDapBizException;
import com.xdap.common.exception.XDapBizExceptionEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @ProjectName techking-plan-plugin
 * @Description
 * @Date 2023/11/16 16:10
 * @Author shangsheng.li
 **/
@Slf4j
@Service
public class ApaasTokenUtil {

    @Value("${xdap.share.frontSingleAppHost}")
    private String appHost;

    @Resource
    private RestClient restClient;

    @Resource
    private RuntimeAppContextService runtimeAppContextService;

    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    public String getAccessToken(String currentUserId) {
        // 查询应用后端接口
        String appBackendUrl = appHost.replace("/app/", "");
        // 根据账号获取token信息
        String l = System.currentTimeMillis() + "";
        Map<String, Object> paramsMap = new HashMap<>();
        String clientId = ComPluginPropertiesUtil.getProperty("techking.apaas.app.clientId");
        String clientSecret = ComPluginPropertiesUtil.getProperty("techking.apaas.app.clientSecret");
        paramsMap.put(ComConst.GRANT_TYPE, "client_credentials");
        paramsMap.put(ComConst.CLIENT_ID, clientId);
        paramsMap.put(ComConst.CLIENT_SECRET, clientSecret);

        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add(ComConst.XDAPTIMESTAMP, l);
        httpHeaders.add("Content-Type", "application/json;charset=UTF-8");
        String appTokenUrl = ComPluginPropertiesUtil.getProperty("apaas.api.token.accessToken");
        String fullURL = restClient.getFullURL(appBackendUrl + appTokenUrl, paramsMap);
        Map appTokenResult = restClient.post(fullURL, new HashMap<>(), Map.class, httpHeaders);
        String token = appTokenResult.get("access_token").toString();

        paramsMap = new HashMap<>();
        paramsMap.put(ComConst.TOKEN, token);
        paramsMap.put(ComConst.USER_ID, currentUserId);

        httpHeaders = new HttpHeaders();
        httpHeaders.add(ComConst.XDAPTIMESTAMP, l);
        httpHeaders.add("Content-Type", "application/json;charset=UTF-8");
        String userTokenUrl = ComPluginPropertiesUtil.getProperty("apaas.api.token.userToken");
        Map map = restClient.get(appBackendUrl + userTokenUrl, paramsMap, Map.class, httpHeaders);
        String accessToken = map.get("access_token").toString();
        if (StringUtils.isBlank(token)) {
            throw new XDapBizException(XDapBizExceptionEnum.TOKEN_ERROR);
        }
        return accessToken;
    }

    /**
     * @Package com.xdap.dcpc.service
     * @Description: (获取access_token)
     * @date 2021/10/25
     * @version V1.0
     */
    public JSONObject getAccessToken() {
        String clientId = ComPluginPropertiesUtil.getProperty("techking.apaas.app.clientId");
        String clientSecret = ComPluginPropertiesUtil.getProperty("techking.apaas.app.clientSecret");
        String key = String.format("%s:%s:%s", this.runtimeAppContextService.getCurrentTenantId(),
                this.runtimeAppContextService.getCurrentAppId(), "access_token");
        log.info("key:{}", JSON.toJSONString(key));
        Object o = redisTemplate.opsForValue().get(key);
        log.info("object:{}", JSON.toJSONString(o));
        if (ObjectUtils.isNotEmpty(o)) {
            return JSONObject.parseObject(String.valueOf(o));
        } else {
            String replace = appHost.replace("/app/", "");
            Map<String, Object> requestMap = new HashMap<>();
            // 发送请求
            RestTemplate restTemplate = new RestTemplate();
            HttpHeaders head = new HttpHeaders();
            head.add("Content-Type", "application/json;charset=UTF-8");
            HttpEntity<String> requestEntity = new HttpEntity<String>(JSONObject.toJSONString(requestMap), head);
            String appTokenUrl = ComPluginPropertiesUtil.getProperty("apaas.api.token.accessToken");
            String uri = replace + appTokenUrl + "?grant_type=client_credentials&client_id=" + clientId + "&client_secret=" + clientSecret;
            String entity = restTemplate.postForObject(uri, requestEntity, String.class);
            JSONObject jsonObject = JSON.parseObject(entity);
            log.info("getAccessToken：{}", JSON.toJSONString(jsonObject));
            String expiresIn = jsonObject.get("expires_in").toString();
            redisTemplate.opsForValue().set(key, JSON.toJSONString(jsonObject), Long.parseLong(expiresIn), TimeUnit.SECONDS);
            return jsonObject;

        }
    }

    /**
     * @Package com.xdap.dcpc.service
     * @Description: (获取user_token)
     * @date 2021/10/29
     * @version V1.0
     */
    public JSONObject getUserAccessToken(String token, String userId) throws InterruptedException {
        String replace = appHost.replace("/app/", "");
        Map<String, Object> requestMap = new HashMap<>();
        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders head = new HttpHeaders();
        head.add("Content-Type", "application/json;charset=UTF-8");
        HttpEntity<String> requestEntity = new HttpEntity<String>(JSONObject.toJSONString(requestMap), head);
        String userTokenUrl = ComPluginPropertiesUtil.getProperty("apaas.api.token.userToken");
        String uri = replace + userTokenUrl + "?token=" + token + "&userId=" + userId;
        ResponseEntity<String> entity = restTemplate.exchange(uri, HttpMethod.GET, requestEntity, String.class);
        JSONObject jsonObject = JSON.parseObject(entity.getBody());
        if (HttpStatus.UNAUTHORIZED.equals(entity.getStatusCode())) {
            Thread.sleep(2000L);
            JSONObject accessToken = this.getAccessToken();
            uri = replace + userTokenUrl + "?token=" + accessToken + "&userId=" + userId;
            entity = restTemplate.exchange(uri, HttpMethod.GET, requestEntity, String.class);
            jsonObject = JSON.parseObject(entity.getBody());
        }
        log.info("getUserAccessToken：{}", JSON.toJSONString(jsonObject));
        return jsonObject;
    }

    public String createToken(String userId) {
        log.info("userId:{}", userId);
        Map<String, Object> claims = new HashMap<>();
        claims.put("xdapuserid", userId);
        if (userId == null) {
            throw new XDapSystemException(ExceptionMessage.XDAP_INVALID_USER);
        } else {
            String token = JwtUtils.createJWT(claims, 7200000L);
            String refreshToken = JwtUtils.createJWT(claims, 1209600000L);
            this.stringRedisTemplate.opsForValue().set(token, refreshToken, 1209600000L,
                    TimeUnit.MILLISECONDS);
            return token;
        }
    }

}
